package com.netsdk.lht2.push;

import com.netsdk.demo.util.sql.Trajectory;
import com.netsdk.lht2.util.TrajectoryUtil;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

// 先东西直行(1)，右转，左转，再南北 直行，右转，左转
public class RoadVehicleDataCblPcl_Backup {
    Map<String, List<Trajectory[]>> data = new HashMap<>();
    Map<Direction, List<String>> directionMapping = new HashMap<>();
    Set<String> channelSet = new HashSet<>();
    String utc ;
    private final static DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    {
        channelSet.add("367");
        channelSet.add("368");
        channelSet.add("369");
        channelSet.add("329");

        List<String> straight = new ArrayList<>();
        straight.add("369-2");
        straight.add("369-3");
        straight.add("367-2");
        straight.add("367-3");
        directionMapping.put(Direction.straight,straight);
        List<String> right = new ArrayList<>();
        right.add("369-3-");
        right.add("367-3-");
        directionMapping.put(Direction.right,right);
        List<String> left = new ArrayList<>();
        left.add("369-1");
        left.add("367-1");
        directionMapping.put(Direction.left,left);

        List<String> straight2 = new ArrayList<>();
        straight2.add("368-2");
        straight2.add("368-3");
        straight2.add("329-2");
        straight2.add("329-3");
        directionMapping.put(Direction.straight2,straight2);
        List<String> right2 = new ArrayList<>();
        right2.add("368-4");
        right2.add("329-3-");
        directionMapping.put(Direction.right2,right2);
        List<String> left2 = new ArrayList<>();
        left2.add("368-1");
        left2.add("329-1");
        directionMapping.put(Direction.left2,left2);

    }

    public RoadVehicleDataCblPcl_Backup(String utc) {
        this.utc = utc;
    }

    public void addData(String channel,String nlane,List<Trajectory[]> arr){
        String index = channel + "-" + nlane;
        List<Trajectory[]> trajectories = data.get(index);
        if(trajectories == null){
            data.put(index,arr);
        }else {
            index += "-";
            data.put(index,arr);
        }
    }

    public boolean support(String channel){
        return channelSet.contains(channel);
    }

    public String getPushData(){
        LocalDateTime endTime = deal(false);
        // 更新日期
        TimeCacheUtil.TimeRecored timeRecored = TimeCacheUtil.get2(utc);
        timeRecored.setEndTime(endTime);
        timeRecored.status = 2;

        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, List<Trajectory[]>> entry : data.entrySet()) {
            List<Trajectory[]> value = entry.getValue();
            String body = TrajectoryUtil.toPushStringList(value);
            sb.append(body);
        }
        return sb.toString();
    }
    private boolean redo = false;


    private LocalDateTime addTrajectoryTime(LocalDateTime startTime,Direction direction,boolean flag){
        List<String> indexList = directionMapping.get(direction);
        LocalDateTime endTime = startTime;
        for (String index : indexList) {
            List<Trajectory[]> trajectories = data.get(index);
            if(trajectories == null)continue;
            LocalDateTime oneEndTime = dealTime(trajectories, startTime, flag);
            if(oneEndTime.isAfter(endTime)){
                endTime = oneEndTime;
            }
        }
        return endTime;
    }

    private LocalDateTime deal(boolean flag) {
        if(!redo){
            proprocess();
        }
        TimeCacheUtil.TimeRecored timeRecored = TimeCacheUtil.get2(utc);
        LocalDateTime startTime = timeRecored.getStartTime();
        timeRecored.status = 1;
        // 计算 东西直行时间  ,数量+偏移7秒
        // 平城路-城北路-西侧-东HG  369 2,3
        // LocalDateTime straightTime = addTrajectoryTime(startTime, Direction.straight, flag);

        List<Trajectory[]> trajectories = data.get("369-2");
        LocalDateTime endTime1 = dealTime(trajectories, startTime,flag);
        List<Trajectory[]> trajectories2 = data.get("369-3");
        LocalDateTime endTime2 = dealTime(trajectories2, startTime,flag);
        // 平城路-城北路-东侧-西HG	367 2,3
        List<Trajectory[]> trajectories3 = data.get("367-2");
        LocalDateTime endTime3 = dealTime(trajectories3, startTime,flag);
        List<Trajectory[]> trajectories4 = data.get("367-3");
        LocalDateTime endTime4 = dealTime(trajectories4, startTime,flag);
        LocalDateTime straightTime = findMax(endTime1, endTime2, endTime3, endTime4);
        if(redo){
            straightTime = plusEightSeconds(straightTime,8,trajectories,trajectories2,trajectories3,trajectories4);
        }else{
            straightTime = plusEightSeconds(straightTime,5,trajectories,trajectories2,trajectories3,trajectories4);
        }

        // 计算 东西右转时间
        // 陈家山路-胜辛路-西侧-东HG  369 3
        // 陈家山路-胜辛路-东侧-西HG	367 3
        LocalDateTime rightTimeOffset = startTime.plusSeconds(4);
        List<Trajectory[]> trajectories5 = data.get("369-3-");
        LocalDateTime endTime5 = dealTime(trajectories5, rightTimeOffset,flag);
        List<Trajectory[]> trajectories6 = data.get("367-3-");
        LocalDateTime endTime6 = dealTime(trajectories6, rightTimeOffset,flag);
        LocalDateTime rightTime = findMax(endTime5, endTime6);
        if(redo){
            rightTime = plusEightSeconds(rightTime,8,trajectories5,trajectories6);

        }else{
            rightTime = plusEightSeconds(rightTime,5,trajectories5,trajectories6);
        }

        // 计算 东西左转时间
        // 平城路-城北路-西侧-东HG   369 1
        // 平城路-城北路-东侧-西HG	367 1
        LocalDateTime leftTimeOffset = findMax(straightTime,rightTime).plusSeconds(1);
        List<Trajectory[]> trajectories7 = data.get("369-1");
        LocalDateTime endTime7 = dealTime(trajectories7, leftTimeOffset,flag);
        List<Trajectory[]> trajectories8 = data.get("367-1");
        LocalDateTime endTime8 = dealTime(trajectories8, leftTimeOffset,flag);
        LocalDateTime leftTime = findMax(endTime7, endTime8);
        if(redo){
            leftTime = plusEightSeconds(leftTime,8,trajectories7,trajectories8);
        }else {
            leftTime = plusEightSeconds(leftTime,5,trajectories7,trajectories8);
        }

        // 计算 南北直行时间
        // 城北路-平成路-南侧-北HG	368 2,3
        // 城北路-平成路-北侧-南	329 2,3
        LocalDateTime straightTimeOffset = leftTime;
        List<Trajectory[]> trajectories9 = data.get("368-2");
        LocalDateTime endTime9 = dealTime(trajectories9, straightTimeOffset,flag);
        List<Trajectory[]> trajectories10 = data.get("368-3");
        LocalDateTime endTime10 = dealTime(trajectories10, straightTimeOffset,flag);
        List<Trajectory[]> trajectories11 = data.get("329-2");
        LocalDateTime endTime11 = dealTime(trajectories11, straightTimeOffset,flag);
        List<Trajectory[]> trajectories12 = data.get("329-3");
        LocalDateTime endTime12 = dealTime(trajectories12, leftTime,flag);
        LocalDateTime straightTime2 = findMax(endTime9, endTime10,endTime11,endTime12);
        if(redo){
            straightTime2 = plusEightSeconds(straightTime2,8,trajectories9,trajectories10,trajectories11,trajectories12);
        }else {
            straightTime2 = plusEightSeconds(straightTime2,5,trajectories9,trajectories10,trajectories11,trajectories12);
        }
        // 计算 南北右转时间
        // 城北路-平成路-南侧-北HG	368 4
        // 城北路-平成路-北侧-南	329  3
        LocalDateTime rightTimeOffset2 = straightTimeOffset;
        List<Trajectory[]> trajectories14 = data.get("368-4");
        LocalDateTime endTime14 = dealTime(trajectories14, rightTimeOffset2,flag);
        List<Trajectory[]> trajectories15 = data.get("329-3-");
        LocalDateTime endTime15 = dealTime(trajectories15, rightTimeOffset2,flag);
        LocalDateTime rightTime2 = findMax(endTime14, endTime15);
        rightTime2 = plusEightSeconds(rightTime2,5,trajectories14,trajectories15);

        // 计算 南北左转时间
        // 城北路-平成路-南侧-北HG	368  1
        // 城北路-平成路-南侧-北HG	329  1
        LocalDateTime leftTimeOffset2 = findMax(rightTime2,straightTime2);
        List<Trajectory[]> trajectories16 = data.get("368-1");
        LocalDateTime endTime16 = dealTime(trajectories16, leftTimeOffset2,flag);
        List<Trajectory[]> trajectories17 = data.get("329-1");
        LocalDateTime endTime17 = dealTime(trajectories17, leftTimeOffset2,flag);
        LocalDateTime leftTime2 = findMax(endTime16, endTime17);
        leftTime2 = plusEightSeconds(leftTime2,5,trajectories16,trajectories17);
        if(redo){
            System.out.println(utc + "，重构后最终使用时间："+leftTime2);
        }else {
            System.out.println(utc + "，最终使用时间："+leftTime2);
        }
        if(!redo){
            if(leftTime2.isAfter(startTime.plusMinutes(1))){
                System.out.println("超时："+leftTime2);
            }
            Duration duration = Duration.between(leftTime2,startTime.plusMinutes(1));
            if(duration.toMillis()>10000){
                redo = true;
                leftTime2 = deal(true);
            }
        }
        return leftTime2;
    }

    // 数据预处理
    private void proprocess() {
        List<String> straight = directionMapping.get(Direction.straight);
        int straightCount = countSum(straight);

        List<String> right = directionMapping.get(Direction.right);
        int rightCount = countSum(right);

        List<String> left = directionMapping.get(Direction.left);
        int leftCount = countSum(left);

        List<String> straight2 = directionMapping.get(Direction.straight2);
        int straight2Count = countSum(straight2);

        List<String> right2 = directionMapping.get(Direction.right2);
        int right2Count = countSum(right2);

        List<String> left2 = directionMapping.get(Direction.left2);
        int left2Count = countSum(left2);
        int total = Math.max(straightCount,rightCount)+leftCount+Math.max(straight2Count,right2Count)+left2Count;
        int maxNum = 22;
        if(total < maxNum){
            // 补充车辆数据
            int addNum = maxNum-total;
            // 直行
            fillVichleData((int)(addNum*0.3)+1, Direction.straight);
            // 左转
            fillVichleData( (int)(addNum*0.1)+1, Direction.left);
            // 右转
            fillVichleData( (int)(addNum*0.1)+1, Direction.right);

            fillVichleData( (int)(addNum*0.3)+1, Direction.straight2);
            fillVichleData( (int)(addNum*0.1)+1, Direction.left2);
            fillVichleData( (int)(addNum*0.1)+1, Direction.right2);
        }
    }

    public void fillVichleData(int num,Direction direction){
        for (int i = 0; i < num; i++) {
            List<String> mapping = directionMapping.get(direction);
            int length = mapping.size();
            String randomIndex = mapping.get(getRandom(length));
            List<Trajectory[]> trajectories = data.get(randomIndex);
            if(trajectories == null){
                trajectories = new ArrayList<>();
                data.put(randomIndex,trajectories);
            }
            trajectories.addAll(TrajectoryUtil.create(TimeCacheUtil.formateUtc(utc),1,randomIndex.substring(0,3),randomIndex.substring(4)));
        }
    }


    public static void main(String[] args) {
        System.out.println("367-1-".substring(0,3));
        System.out.println("367-1-".substring(4));
    }



    private int countSum(List<String> list) {
        int count = 0;
        for (String index : list) {
            List<Trajectory[]> trajectories = data.get(index);
            if(trajectories != null){
                count += trajectories.size();
            }
        }
        return count;
    }

    public int countTotal() {
        List<String> straight = directionMapping.get(Direction.straight);
        int straightCount = countSum(straight);
        System.out.println("straightCount:"+ straightCount);
        List<String> right = directionMapping.get(Direction.right);
        int rightCount = countSum(right);
        System.out.println("rightCount:"+ rightCount);
        List<String> left = directionMapping.get(Direction.left);
        int leftCount = countSum(left);
        System.out.println("leftCount:"+ leftCount);

        List<String> straight2 = directionMapping.get(Direction.straight2);
        int straight2Count = countSum(straight2);
        System.out.println("straight2Count:"+ straight2Count);

        List<String> right2 = directionMapping.get(Direction.right2);
        int right2Count = countSum(right2);
        System.out.println("right2Count:"+ right2Count);

        List<String> left2 = directionMapping.get(Direction.left2);
        int left2Count = countSum(left2);
        System.out.println("left2Count:"+ left2Count);

//        for (Map.Entry<String, List<Trajectory[]>> entry : data.entrySet()) {
//            count += entry.getValue().size();
//            System.out.println(entry.getKey() + "  : "+ entry.getValue().size());
//        }
        return straightCount+rightCount+leftCount+straight2Count+right2Count+left2Count;
    }


    private LocalDateTime plusEightSeconds(LocalDateTime time,int seconds,List<Trajectory[]>... arr){
        if(arr == null){
            return time;
        }
        boolean flag = false;
        for (List<Trajectory[]> trajectories : arr) {
            if(trajectories != null){
                flag = true;
                break;
            }
        }
        if(flag){
            return time.plusSeconds(seconds);
        }
        return time;
    }

    private LocalDateTime dealTime(List<Trajectory[]> data,LocalDateTime startTime,boolean flag){
        if(data==null){
            return startTime;
        }
        int offset = 0;
        LocalDateTime endTime = startTime;
        for (Trajectory[] datum : data) {
            int delay = 0;
            for (Trajectory trajectory : datum) {
                trajectory.setTime(endTime.plusSeconds(delay).format(dateTimeFormatter));
                delay +=1;
            }
//            offset += getRandom();
            if(flag){
                endTime = endTime.plusSeconds(getRandom(2)+1);
            }else {
                endTime = endTime.plusSeconds(1);
            }
        }
        return endTime;
    }

    private static final Random random = new Random();
    private static int getRandom(int bound){
        return random.nextInt(bound);
    }


    private LocalDateTime findMax(LocalDateTime... arr){
        LocalDateTime max = arr[0];
        for (LocalDateTime localDateTime : arr) {
            if (localDateTime.isAfter(max)){
                max = localDateTime;
            }
        }
        return max;
    }


 enum Direction {straight,right,left,straight2,right2,left2}

}
